import os
from typing import Dict
import dearpygui.dearpygui as dpg

import src.date as date
from src.schedule import Duty, Schdule
from src.popup_list import PopupList


class ScheduleTab:
    def __init__(self, doctors: Dict[str, Dict] = [], tag=0, label="排班"):
        self.label = label
        self.dutys = set(Duty.persist())
        self.doctors = doctors
        self.schdule = Schdule()
        year = self.schdule.year
        month = self.schdule.month
        with dpg.theme(tag="red_text_theme"):
            with dpg.theme_component(dpg.mvAll):
                dpg.add_theme_color(dpg.mvThemeCol_Text, (255, 0, 0))
        with dpg.tab(tag=tag, label=label) as tab:
            self.tag = tab
            with dpg.file_dialog(
                label='保存',
                show=False,
                modal=True,
                callback=self.save,
                tag=f"{tab}_save",
                width=700,
                height=400,
            ):
                dpg.add_file_extension(".xlsx")
            with dpg.file_dialog(
                label='导入',
                show=False,
                modal=True,
                callback=self.load,
                tag=f"{tab}_load",
                width=700,
                height=400,
            ):
                dpg.add_file_extension(".xlsx")
            with dpg.group(horizontal=True):
                dpg.add_combo(
                    list(range(year - 10, year + 11)),
                    tag=f"{tab}_year",
                    label="年",
                    default_value=year,
                    width=100,
                    callback=self.change_month,
                )
                dpg.add_combo(
                    list(range(1, 13)),
                    tag=f"{tab}_month",
                    label="月",
                    default_value=month,
                    width=100,
                    callback=self.change_month,
                )
                dpg.add_button(label="节假日")
                with dpg.popup(
                    dpg.last_item(), dpg.mvMouseButton_Left, tag=f"{tab}_holidays"
                ):
                    self.update_holiday()
                dpg.add_button(label="班次", callback=lambda: self.duty_poplist.show())
                self.duty_poplist = PopupList(
                    self.dutys,
                    tag=f"{tab}_dutys",
                    label="班次",
                    persist=set(Duty.persist()),
                    callback=self.update_table,
                )
                dpg.add_button(
                    label="清空", callback=lambda: dpg.show_item(f"{tab}_clean")
                )
                with dpg.popup(
                    dpg.last_item(),
                    dpg.mvMouseButton_Left,
                    tag=f"{tab}_clean",
                    modal=True,
                ):
                    dpg.add_text("确认要清空所有非锁定数据吗？建议先保存再清空！")
                    with dpg.group(horizontal=True):
                        dpg.add_button(label="确认", callback=self.clean)
                        dpg.add_button(
                            label="保存", callback=lambda: self.open_save()
                        )
                        dpg.add_button(
                            label="取消", callback=lambda: dpg.hide_item(f"{tab}_clean")
                        )
                dpg.add_button(label="导入", callback=lambda: self.open_load())
                dpg.add_button(label="保存", callback=lambda: self.open_save())
            dpg.add_table(
                tag=f"{tab}_table",
                freeze_rows=2,
                freeze_columns=1,
                # row_background=True,
                borders_outerH=True,
                borders_outerV=True,
                borders_innerH=True,
                borders_innerV=True,
                scrollY=True,
                scrollX=True,
                policy=dpg.mvTable_SizingFixedFit,
            )
        self.update_table()

    def clean(self):
        dpg.hide_item(f"{self.tag}_clean")
        self.schdule.clean()
        self.update_table()

    def open_load(self):
        dpg.show_item(f"{self.tag}_load")
        name, _ = os.path.splitext(self.schdule.filename)
        dpg.configure_item(f"{self.tag}_load", default_filename=name)

    def open_save(self):
        dpg.hide_item(f"{self.tag}_clean")
        dpg.show_item(f"{self.tag}_save")
        name, _ = os.path.splitext(self.schdule.filename)
        filename = f"{name}_{date.get_time_str()}"
        dpg.configure_item(f"{self.tag}_save", default_filename=filename)

    def load(self, sender, app_data, user_data):
        self.schdule.load(app_data["file_path_name"])

    def save(self, sender, app_data, user_data):
        self.schdule.save(app_data["file_path_name"])

    def change_month(self):
        year = int(dpg.get_value(f"{self.tag}_year"))
        month = int(dpg.get_value(f"{self.tag}_month"))
        self.schdule.change(year, month)
        self.update_holiday()
        self.update_table()

    def set_holiday(self, sender, app_data, user_data):
        if app_data:
            self.schdule.holidays.add(user_data)
        else:
            self.schdule.holidays.remove(user_data)
        self.schdule.save()
        self.update_table()

    def change_duty(self, sender, app_data, user_data):
        key, day = user_data
        if app_data == "值休" and day > 1:
            self.update_table()
            return
        if day > 1 and self.schdule.data[key][day - 2].value == "值":
            self.update_table()
            return
        if (
            self.schdule.data[key][day - 1].value == "值"
            and app_data != "值"
            and day < len(self.schdule.days)
        ):
            self.schdule.data[key][day].value = ""
        self.schdule.data[key][day - 1].value = app_data
        if app_data == "值" and day < len(self.schdule.days):
            self.schdule.data[key][day].value = "值休"
        self.schdule.save()
        self.update_table()

    def add_row(self, sender, app_data, user_data):
        self.schdule.data[app_data] = [Duty() for day in self.schdule.days]
        self.schdule.save()
        self.update_table()

    def delete_row(self, sender, app_data, user_data):
        dpg.hide_item(dpg.get_item_parent(sender))
        del self.schdule.data[user_data]
        self.schdule.save()
        self.update_table()

    def move_row(self, sender, name):
        to = dpg.get_item_user_data(sender)
        if self.schdule.move(name, to):
            self.schdule.save()
            self.update_table()

    def lock(self, sender, app_data, user_data):
        dpg.hide_item(dpg.get_item_parent(sender))
        key, day = user_data
        dutys = self.schdule.data[key]
        dutys[day - 1].lock = app_data
        if dutys[day - 1].value == "值" and day < len(self.schdule.days):
            dutys[day].lock = app_data
        if dutys[day - 1].value == "值休" and day > 1:
            dutys[day - 2].lock = app_data
        self.schdule.save()
        self.update_table()

    def comm(self, sender, app_data, user_data):
        key, day = user_data
        dutys = self.schdule.data[key]
        dutys[day - 1].comm = app_data
        self.schdule.save()
        self.update_table()

    def update_holiday(self):
        name = f"{self.tag}_holidays"
        days = self.schdule.days
        weekdays = self.schdule.weekdays
        holidays = self.schdule.holidays
        dpg.delete_item(name, children_only=True)
        for day, weekday in zip(days, weekdays):
            dpg.add_selectable(
                parent=name,
                label=f"{day} {weekday}",
                user_data=day,
                default_value=day in holidays,
                callback=self.set_holiday,
            )

    def update_table(self):
        name = f"{self.tag}_table"
        dpg.delete_item(name, children_only=True)
        days = self.schdule.days
        weekdays = self.schdule.weekdays
        holidays = self.schdule.holidays
        data = self.schdule.data
        doctors = self.doctors
        # 首行
        dpg.add_table_column(parent=name, width_fixed=True, init_width_or_weight=50)
        for day in days:
            dpg.add_table_column(
                parent=name, label=day, width_fixed=True, init_width_or_weight=40
            )
        stat_cols = ["值", "休", "业余"]
        for col in stat_cols:
            dpg.add_table_column(parent=name, width_fixed=True, init_width_or_weight=40)
        # 日期行
        with dpg.table_row(parent=name):
            dpg.add_button(label="刷新", width=-1, callback=self.update_table)
            for day, weekday in zip(days, weekdays):
                dpg.add_text(weekday)
                if day in holidays:
                    dpg.bind_item_theme(dpg.last_item(), "red_text_theme")
            for col in stat_cols:
                dpg.add_text(col)
        # 数据行
        for key in data:
            arr = data[key]
            stats = self.schdule.stat_doctor(key)
            with dpg.table_row(parent=name):
                # 名字
                with dpg.group(
                    payload_type="rows", drop_callback=self.move_row, user_data=key
                ):
                    with dpg.drag_payload(drag_data=key, payload_type="rows"):
                        dpg.add_text(key)
                    # text = dpg.add_text(key + " " * 10)
                    text = dpg.add_button(label=key, enabled=False, width=-1)
                    with dpg.popup(text, min_size=(0, 0)):
                        dpg.add_button(
                            label="删除",
                            width=50,
                            user_data=key,
                            callback=self.delete_row,
                        )
                    with dpg.tooltip(text):
                        if key in doctors:
                            doctor = doctors[key]
                            for k in doctor:
                                dpg.add_text(doctor[k])
                        else:
                            dpg.add_text("已删除")
                            dpg.bind_item_theme(text, "red_text_theme")
                            dpg.bind_item_theme(dpg.last_item(), "red_text_theme")
                # 班次
                for day in days:
                    duty = arr[day - 1]
                    value = duty.value + ("*" if duty.comm else "")
                    if duty.lock:
                        item = dpg.add_text(value)
                    else:
                        item = dpg.add_combo(
                            list(self.dutys),
                            width=-1,
                            no_arrow_button=True,
                            default_value=value,
                            callback=self.change_duty,
                            user_data=(key, day),
                        )
                    if duty.comm:
                        with dpg.tooltip(item):
                            dpg.add_text(duty.comm)
                    if duty.value:
                        with dpg.popup(item):
                            dpg.add_checkbox(
                                label="锁定",
                                default_value=duty.lock,
                                user_data=(key, day),
                                callback=self.lock,
                            )
                            dpg.add_text("备注(回车保存):")
                            dpg.add_input_text(
                                default_value=duty.comm,
                                on_enter=True,
                                width=100,
                                user_data=(key, day),
                                callback=self.comm,
                            )
                    if day in holidays:
                        dpg.bind_item_theme(item, "red_text_theme")
                # 统计
                for col in stat_cols:
                    dpg.add_text(stats.get(col, 0))
        # 新建行
        rest = list(self.doctors.keys())
        for key in data:
            if key in rest:
                rest.remove(key)
        with dpg.table_row(parent=name):
            dpg.add_combo(
                rest,
                width=-1,
                callback=self.add_row,
                payload_type="rows",
                drop_callback=lambda s, a: self.delete_row(s, None, a),
            )
        # 统计
        with dpg.table_row(parent=name):
            dpg.add_text("值班")
            for day in days:
                count, stats = self.schdule.stat_day(day, "值", self.doctors)
                with dpg.group():
                    dpg.add_text(f"{count}")
                    for key, val in stats.items():
                        dpg.add_text(f"{key}: {val}")
